package controller;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;

import modelInterfaces.AbstractModelFactory;
import modelInterfaces.IResult;
import modelInterfaces.ISubject;
import modelInterfaces.ITest;
import pluginInterfaces.IMetric;
import utils.Codes;
import utils.Messages;
import utils.JFileChooserClass;
import utils.Validations;
import viewInterfaces.AbstractViewFactory;
import viewInterfaces.IViewLoadTestResult;
import controllerInterfaces.IControllerBenchmarkPanel;
import controllerInterfaces.IControllerLoadTestResult;

/**
 * Controller class that sets the parameters to load test.
 * 
 * @author Andy Cullache
 */
public class ControllerLoadTestResult implements IControllerLoadTestResult{
	
	private IViewLoadTestResult view;
	private IControllerBenchmarkPanel myController;

	/**
	 * Default constructor.
	 */
	public ControllerLoadTestResult(){
		view = AbstractViewFactory.getAbstractViewFactory().getLoadTestResultView();
		view.setController(this);
	}
	
	/**
	* Sets the benchmark panel controller as controller of this class.
	* 
	* @param controller      panel controller class benchmark.
	*/
	public void setController(IControllerBenchmarkPanel myController){
		this.myController = myController;
	}
	
	/**
	* Opens a view to set the directory and name of the CSV file.
	* 
	* @return      a set of "String" size 2, contains the name and path of the CSV file.
	*/
	public String[] selectDirectory(){
		return JFileChooserClass.selectFileToRead();
	}

	/**
	* Reads the results of tests from a CSV file and add the test with this results.
	* 
	* @param dir      PATH of the file.
	* @param filename      name of the file.
	* @return      true if read test result from CSV file.
	*/
	@Override
	public boolean readTestResult(String dir, String fileName) {
		ITest testAux = AbstractModelFactory.getModelFactory().getTest();
		testAux.setDirPath(dir);
		testAux.setOutputFile(fileName);
		if(Validations.isValidTestLoad(testAux)){
			boolean ret = readTestFromCSV(testAux);
			if(ret){
				this.myController.getLoadTest().add(testAux);
				return true;
			}
			else{
				view.renderError(Codes.errorReadFileTestResult, Messages.errorReadFileTestResult);
				return false;
			}
		}
		else{
			view.renderError(Codes.errorLoadTestResult, Messages.errorLoadTestResult);
		}
		return false;
	}
	
	/**
	* Reads the results of tests from a CSV file, read the results associated with test given as a parameter.
	* 
	* @param test      test to which are added the results of the file.
	* @return      true if read test result from CSV file.
	*/
	private boolean readTestFromCSV(ITest test){
	    	File fileCSV = null;
	        FileReader fr = null;
	        BufferedReader br = null;
	
	        try {
	           fileCSV = new File (test.getDirPath(),test.getOutputFile());
	           if(!fileCSV.canRead())
	        	   return false;
	           fr = new FileReader (fileCSV);
	           br = new BufferedReader(fr);
	
	           String firstLine;
	           firstLine = br.readLine();
	           String[] data = firstLine.split(",");           
	           
	           String line;
	           String algAux = "";
	    	   List<IResult> resMetList = null;
	           while((line=br.readLine())!=null){
	        	   String[] values = line.split(",");
	        	   test.setName(values[0]+" (loaded)");
	        	   if(!algAux.equals(values[1])){
		        	   algAux = values[1];
		        	   resMetList = new ArrayList<IResult>();
		        	   test.getResultMap().put(algAux, resMetList);
	        	   }
	    		   ISubject subject = AbstractModelFactory.getModelFactory().getUser();
	    		   subject.setId(Integer.parseInt(values[2]));
	    		   int variable = Integer.parseInt(values[3]);
	        	   for(int i=4; i<data.length; i++){
	        		   IMetric metSet = AbstractModelFactory.getModelFactory().getMetricSetup();
	        		   IResult resMet = AbstractModelFactory.getModelFactory().getResultMetric();
	        		   resMet.setVariable(variable);
	        		   resMet.setSubject(subject);
	        		   metSet.setName(data[i]);
	        		   resMet.setMetric(metSet);
	        		   resMet.setResultAverage(Double.parseDouble(values[i]));
	        		   resMetList.add(resMet);
	        	   }
	           }
	           return true;
	        }
	        catch(Exception e){
	           e.printStackTrace();
	        }finally{
	           try{                    
	              if( null != fr ){   
	                 fr.close();     
	              }                  
	           }catch (Exception e2){ 
	              e2.printStackTrace();
	           }
	        }
	        return false;
	}


	/**
	 * Updates the table of test results on the benchmark tab.
	 */
	@Override
	public void updateTable() {
		this.myController.setTable();
	}

}
